package com.smart.tool.log;

import java.util.Map;

import com.smart.tool.log.impl.DefaultLoggerFormatter;
import com.smart.tool.log.impl.FastJsonSerialization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Author gao.gwq
 * @Version SmartLogger.java, v 0.1 2023年11月28日 20:30 gao.gwq
 * @Description: TODO
 */
public class SmartLogger {

    private static Logger selfLogger = LoggerFactory.getLogger(SmartLogger.class);
    private static DefaultLoggerFormatter defaultFormatter = new DefaultLoggerFormatter();
    private static LoggerFormatter formatter;

    /**
     * 默认使用FastJsonSerialization作为序列化日志的方式
     */
    private static SerializationLogger serializationLogger = new FastJsonSerialization();

    private static  boolean serializationFlag = false;


    /**
     * 如果需要自己的序列化的方式，可以在系统启动的时候设置这个日志打印的方式方式
     * @param serialization
     */
    public synchronized static void updateSerializationLogger(SerializationLogger serialization) {
        if(serializationFlag) {
            return ;
        }
        serializationLogger = serialization;
        serializationFlag = true;
    }


    public static void init(LoggerFormatter loggerFormatter) {
        formatter = loggerFormatter;
    }

    public static final void debugForBusiness(Logger logger, String domainType, String business, String bizId, String businessKeyFormat,
        Map<String, Object> paramMap, Object businessReturn) {
        if (logger.isDebugEnabled()) {
            String str = getLogForBusinessStr(domainType, business, bizId, businessKeyFormat, paramMap, businessReturn);
            logger.debug(str);
        }

    }

    public static final void infoForBusiness(Logger logger, String domainType, String business, String bizId, String businessKeyFormat,
        Map<String, Object> paramMap, Object businessReturn) {
        if (logger.isInfoEnabled()) {
            String str = getLogForBusinessStr(domainType, business, bizId, businessKeyFormat, paramMap, businessReturn);
            logger.info(str);
        }

    }

    public static final void warnForBusiness(Logger logger, String domainType, String business, String bizId, String businessKeyFormat,
        Map<String, Object> paramMap, Object businessReturn) {
        if (logger.isErrorEnabled()) {
            String str = getLogForBusinessStr(domainType, business, bizId, businessKeyFormat, paramMap, businessReturn);
            logger.warn(str);
        }

    }

    public static final void errorForBusiness(Logger logger, String domainType, String business, String bizId, String businessKeyFormat,
        Map<String, Object> paramMap, Object businessReturn) {
        if (logger.isErrorEnabled()) {
            String str = getLogForBusinessStr(domainType, business, bizId, businessKeyFormat, paramMap, businessReturn);
            logger.error(str);
        }

    }

    private static String getLogForBusinessStr(String domainType, String business, String bizId, String businessKeyFormat,
        Map<String, Object> paramMap, Object resultData) {
        if (formatter == null) {
            formatter = defaultFormatter;
        }

        String logStr = null;

        try {
            logStr = formatter.format(domainType, business, bizId, businessKeyFormat,
                parseObjectParams(paramMap == null ? null : paramMap.values().toArray()), parseObjectParam(paramMap),
                parseObjectParam(resultData));
        } catch (Throwable throwable) {
            selfLogger.error(throwable.getMessage(), throwable);
        }

        return logStr;
    }

    /**
     * 将返回结果进行序列化
     * 1、如果是字符串直接返回结果
     * 2、如果
     *
     * @param businessParameter
     * @return
     */
    public static final String parseObjectParam(Object businessParameter) {
        if (businessParameter != null) {
            if (businessParameter instanceof String) {
                return (String)businessParameter;
            }
           else
            {
                return businessParameter instanceof Throwable ? //processExceptionMsg((Throwable)businessParameter)
                    formatter.printStackInfo((Throwable)businessParameter) :
                        serializationLogger.serialization(businessParameter);
            }
        } else {
            return null;
        }
    }


    /*private static Throwable getThrowable(Throwable throwable) {
        if (throwable == null) {
            return throwable;
        }
        Throwable rootCause = ExceptionUtils.getRootCause(throwable);
        return rootCause != null ? rootCause : throwable;
    }

    private static String processExceptionMsg(Throwable throwable) {
        if (throwable == null) {
            return "";
        }
        StringBuilder trackTrace = new StringBuilder();
        if (StringUtils.isNotBlank(throwable.getMessage())) {
            trackTrace.append("Message:").append(throwable.getMessage().replace("\n", "@&")).append("@&");
        } else {
            trackTrace.append("Message:").append(" <").append(throwable.toString()).append("> ");
        }
        StackTraceElement[] trace = throwable.getStackTrace();
        int length = trace != null && trace.length > STACK_LEVEL ? STACK_LEVEL : (trace != null ? trace.length : 0);
        for (int i = 0; i < length; i++) {
            StackTraceElement traceElement = trace[i];
            trackTrace.append(traceElement.toString()).append("@&");
        }
        return trackTrace.toString();

    }*/

    public static final String[] parseObjectParams(Object[] businessParameters) {
        if (businessParameters == null || businessParameters.length == 0) {
            return null;
        }
        String[] paramArr = new String[businessParameters.length];

        for (int i = 0; i < businessParameters.length; ++i) {
            paramArr[i] = parseObjectParam(businessParameters[i]);
        }

        return paramArr;

    }

    public static LoggerFormatter getFormatter() {
        return formatter;
    }

    public synchronized static void setFormatter(LoggerFormatter loggerFormatter) {
        formatter = loggerFormatter;
    }

    static {
        formatter = defaultFormatter;
    }
}
